package com.experiment08;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.Comparator;

public class IOTest {
    public static void main(String[] args) {
        String fileName = "C:/example/from.txt";

        System.out.println("----- 创建文件 ------");
        createFile(fileName);

        System.out.println("-----  将字符串写入文件 -------");
        // \r\n在txt文本中换行
        String str =
                "白日依山尽\r\n" +
                        "黄河入海流\r\n" +
                        "欲穷千里目\r\n" +
                        "更上一层楼\r\n";
        writeToFile(fileName, str);
        writeToFile2(fileName, str);

        System.out.println("--------- 基于基本IO流实现文件的复制 ----------");
        String toFile = "C:/example/to.txt";
        copyByIO(fileName, toFile);

        System.out.println("--------- 基于NIO实现文件的复制 ----------");
        String toFile2 = "C:/example/nio/to.txt";
        copyByNIO(fileName, toFile2);

        /*System.out.println("---------- 删除指定文件 -------------");
        deleteFile(toFile);*/

        System.out.println("---------- 遍历指定目录文件 -------------");
        String dir = "C:/example";
        walkDirectories(dir);
    }

    /**
     * 基于Path/Files实现
     * 将传入的文件绝对路径字符串转path
     * 判断path不存在，则先创建目录，创建文件
     * 文件存在，忽略操作
     *
     * @param fileName
     */
    private static void createFile(String fileName) {
        Path p = Path.of(fileName);
        try {
            if(Files.exists(p)) {
                System.out.println("文件已存在");
            }
            else {
                //目录存在，不操作；目录不存在，创建目录
                Files.createDirectories(p.getParent());
                Files.createFile(p);
                System.out.println("文件创建成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 注意，传入的fileName为文件绝对路径，必须确保文件所在目录已经存在，才能通过FileOutputStream创建
     * 将字符串转字节数组，基于FileOutputStream直接写入
     *
     * @param fileName
     * @param content
     */
    private static void writeToFile(String fileName, String content) {
        Path p = Path.of(fileName);
        try {
            //确保文件所在目录已经存在
            Files.createDirectories(p.getParent());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try(OutputStream out = new FileOutputStream(fileName)){
                //文件不存在时，创建并写入，文件存在时，覆盖写入
                out.write(content.getBytes());
                System.out.println("字符串写入成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        }



    /**
     * 将传入的文件绝对路径字符串转path，通过Files创建文件所在目录
     * 将字符串，基于Files工具类直接写入。写入方法，文件不存在创建并写入，存在则覆盖写入
     * 字符串转字节数组再写入也可，但无意义
     *
     * @param fileName
     * @param content
     */
    // Files.writeString(Paths.get(path), content);
    private static void writeToFile2(String fileName, String content) {
        Path p = Path.of(fileName);
        try {
            //确保文件目录存在
            Files.createDirectories(p.getParent());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(Files.notExists(p)) {
                    //文件不存在，创建文件
                    Files.createFile(p);
                }
                Files.writeString(p, content);
                System.out.println("字符串写入成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }



    /**
     * 基于基本IO，以及字节数组缓冲区，复制文件
     * 打印显示循环读写循环次数
     * 正确关闭资源
     *
     * @param sourceFile
     * @param targetFile
     */
    private static void copyByIO(String sourceFile, String targetFile) {
        try (InputStream in = new FileInputStream(sourceFile);
             OutputStream out = new FileOutputStream(targetFile)) {
            int size = 6;
            byte[] buffer = new byte[size];
            int len;
            int i = 1;
            while ((len = in.read(buffer)) != -1) {
                System.out.println("第" + i++ +"次循环，写入: " + Arrays.toString(buffer));
                out.write(buffer, 0, len);
            }
            System.out.println("copyByIO 成功");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 基于NIO，实现文件的复制
     * 注意，判断目标为字符串，需要转为path并创建相应目录
     *
     * @param sourceFile
     * @param targetFile
     */
    private static void copyByNIO(String sourceFile, String targetFile) {
        Path pin = Path.of(sourceFile);
        Path pout = Path.of(targetFile);
        try {
            //确保文件目录存在
            if (Files.notExists(pout.getParent())) {
                Files.createDirectories(pout.getParent());
            }
            // 复制文件，覆盖式复制
            Files.copy(pin, pout, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("copyByNIO 成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除文件
     *
     * @param fileName
     */
    private static void deleteFile(String fileName) {
        Path path =Path.of(fileName);
        try {
            //若存在则删除，不存在则不删除，返回是否成功删除
            if(Files.deleteIfExists(path)){
                System.out.println("删除文件成功");
            }
            else{
                System.out.println("删除文件失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 遍历打印指定目录下全部目录/文件名称
     * 尝试改变正逆序操作方法
     *
     * @param dir
     */
    private static void walkDirectories(String dir) {
        Path path  = Path.of(dir);
        try {
            System.out.println("正序:");
            Files.walk(path)
                    //正序（先目录后文件）输出
                    .forEach(System.out::println);
            System.out.println("逆序:");
            Files.walk(path)
                    .sorted(Comparator.reverseOrder())
                    .forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

